{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1.8 Exploring the mesh topology\n",
    "\n",
    "In this tutorial, we learn how to iterate over mesh entities and obtain information about how one mesh entity is connected to others, e.g.: \n",
    "- what edges are connected to a vertex?\n",
    "- what are the edges of an element?\n",
    "- what are points of an element? \n",
    "- what elements are adjacent to a face?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import netgen.gui\n",
    "%gui tk\n",
    "from ngsolve import *\n",
    "from netgen.csg import unit_cube"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "mesh = Mesh(unit_cube.GenerateMesh(maxh=1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Iterating over mesh objects\n",
    "\n",
    "##### Iterating over vertices:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "V0 (0.0, 0.0, 0.0)\n",
      "V1 (0.0, 0.0, 1.0)\n",
      "V2 (1.0, 0.0, 0.0)\n",
      "V3 (0.0, 1.0, 0.0)\n",
      "V4 (1.0, 0.0, 1.0)\n",
      "V5 (0.0, 1.0, 1.0)\n",
      "V6 (1.0, 1.0, 0.0)\n",
      "V7 (1.0, 1.0, 1.0)\n",
      "V8 (0.500000000001051, 0.5000000000013137, 0.5000000000010585)\n"
     ]
    }
   ],
   "source": [
    "for v in mesh.vertices:    \n",
    "    print (v, v.point)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What is the type of `v` in `mesh.vertices`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n",
      "<class 'ngsolve.comp.MeshNode'>\n"
     ]
    }
   ],
   "source": [
    "for v in mesh.vertices:    \n",
    "    print(type(v))   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll shortly return to this `MeshNode` class."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Iterating over elements:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V4, V5, V8, V7)\n",
      "edges:  (E19, E21, E25, E17, E20, E22)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V0, V1, V8, V2)\n",
      "edges:  (E1, E6, E12, E0, E5, E9)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V1, V2, V4, V8)\n",
      "edges:  (E9, E12, E20, E6, E7, E10)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V0, V3, V8, V5)\n",
      "edges:  (E3, E13, E22, E2, E5, E16)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V1, V4, V5, V8)\n",
      "edges:  (E9, E20, E22, E7, E8, E17)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V0, V2, V8, V6)\n",
      "edges:  (E4, E11, E24, E1, E5, E12)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V0, V3, V6, V8)\n",
      "edges:  (E5, E16, E24, E2, E4, E14)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V0, V1, V5, V8)\n",
      "edges:  (E5, E9, E22, E0, E3, E8)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V2, V4, V8, V6)\n",
      "edges:  (E11, E18, E24, E10, E12, E20)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V4, V6, V7, V8)\n",
      "edges:  (E20, E24, E25, E18, E19, E23)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V3, V6, V8, V7)\n",
      "edges:  (E15, E23, E25, E14, E16, E24)\n",
      "<class 'ngsolve.comp.Ngs_Element'>\n",
      "vertices:  (V3, V5, V7, V8)\n",
      "edges:  (E16, E22, E25, E13, E15, E21)\n"
     ]
    }
   ],
   "source": [
    "for el in mesh.Elements(VOL):\n",
    "    print(type(el))\n",
    "    print (\"vertices: \", el.vertices)   # get vertices of an element \n",
    "    print (\"edges: \", el.edges)         # get edges of an element "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NodeId and MeshNodes\n",
    "\n",
    "An object of type NodeId in NGSolve is just a number together with a type of the mesh entity it describes.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "type =  NODE_TYPE.VERTEX v.nr = 0\n"
     ]
    }
   ],
   "source": [
    "v = NodeId(VERTEX,0)\n",
    "type(v)\n",
    "print (\"type = \", v.type, \"v.nr =\", v.nr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on NodeId in module ngsolve.comp object:\n",
      "\n",
      "class NodeId(pybind11_builtins.pybind11_object)\n",
      " |  an node identifier containing node type and node nr\n",
      " |  \n",
      " |  Method resolution order:\n",
      " |      NodeId\n",
      " |      pybind11_builtins.pybind11_object\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __eq__(...)\n",
      " |      __eq__(self: ngsolve.comp.NodeId, arg0: ngsolve.comp.NodeId) -> bool\n",
      " |  \n",
      " |  __hash__(...)\n",
      " |      __hash__(self: ngsolve.comp.NodeId) -> int\n",
      " |  \n",
      " |  __init__(...)\n",
      " |      __init__(self: ngsolve.comp.NodeId, arg0: ngsolve.fem.NODE_TYPE, arg1: int) -> None\n",
      " |  \n",
      " |  __ne__(...)\n",
      " |      __ne__(self: ngsolve.comp.NodeId, arg0: ngsolve.comp.NodeId) -> bool\n",
      " |  \n",
      " |  __repr__(...)\n",
      " |      __repr__(self: ngsolve.comp.NodeId) -> str\n",
      " |  \n",
      " |  __str__(...)\n",
      " |      __str__(self: ngsolve.comp.NodeId) -> str\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  nr\n",
      " |      the node number\n",
      " |  \n",
      " |  type\n",
      " |      the node type\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pybind11_builtins.pybind11_object:\n",
      " |  \n",
      " |  __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n",
      " |      Create and return a new object.  See help(type) for accurate signature.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`NODE_TYPE` can be one of the following:\n",
    "\n",
    "- `VERTEX`: dimension 0 \n",
    "- `EDGE`: dimension 1\n",
    "- `FACE`: dimension 2\n",
    "- `CELL`: dimension 3\n",
    "- `ELEMENT`: codimension 0\n",
    "- `FACET`: codimension 1 \n",
    "\n",
    "E.g., in $n$ space dimensions, facets are mesh objects of dimension $n-1$. When $n=3$ there are no `CELL` entities.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nodes can be associated to existing mesh. Consider the above-defined node \n",
    "```\n",
    "v = NodeId(VERTEX,0)\n",
    "```\n",
    "It can be associated to `mesh`. Then it becomes an object of type `MeshNode` which has coordinate information."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "point =  (0.0, 0.0, 0.0)\n"
     ]
    }
   ],
   "source": [
    "meshv = mesh[v]\n",
    "print (\"type = \", type(meshv))\n",
    "print (\"point = \", meshv.point)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(ngsolve.comp.NodeId, ngsolve.comp.MeshNode)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(v), type(meshv)   # note the differnt types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on MeshNode in module ngsolve.comp object:\n",
      "\n",
      "class MeshNode(NodeId)\n",
      " |  a node within a mesh\n",
      " |  \n",
      " |  Method resolution order:\n",
      " |      MeshNode\n",
      " |      NodeId\n",
      " |      pybind11_builtins.pybind11_object\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __init__(self, /, *args, **kwargs)\n",
      " |      Initialize self.  See help(type(self)) for accurate signature.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  edges\n",
      " |      tuple of global edge numbers\n",
      " |  \n",
      " |  elements\n",
      " |      tuple of global element-ids\n",
      " |  \n",
      " |  faces\n",
      " |      tuple of global face numbers\n",
      " |  \n",
      " |  point\n",
      " |      vertex coordinates\n",
      " |  \n",
      " |  vertices\n",
      " |      tuple of global vertex numbers\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from NodeId:\n",
      " |  \n",
      " |  __eq__(...)\n",
      " |      __eq__(self: ngsolve.comp.NodeId, arg0: ngsolve.comp.NodeId) -> bool\n",
      " |  \n",
      " |  __hash__(...)\n",
      " |      __hash__(self: ngsolve.comp.NodeId) -> int\n",
      " |  \n",
      " |  __ne__(...)\n",
      " |      __ne__(self: ngsolve.comp.NodeId, arg0: ngsolve.comp.NodeId) -> bool\n",
      " |  \n",
      " |  __repr__(...)\n",
      " |      __repr__(self: ngsolve.comp.NodeId) -> str\n",
      " |  \n",
      " |  __str__(...)\n",
      " |      __str__(self: ngsolve.comp.NodeId) -> str\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from NodeId:\n",
      " |  \n",
      " |  nr\n",
      " |      the node number\n",
      " |  \n",
      " |  type\n",
      " |      the node type\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pybind11_builtins.pybind11_object:\n",
      " |  \n",
      " |  __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n",
      " |      Create and return a new object.  See help(type) for accurate signature.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help (meshv)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`MeshNode` objects like `meshv` can be queried for topology information. \n",
    "\n",
    "E.g.,  what are edges connected to the mesh vertex `meshv`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(E0, E1, E2, E3, E4, E5, E6, E8, E9, E11, E12, E13, E14, E16, E22, E24)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "meshv.edges"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(F11, F4, F0, F2)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = NodeId(CELL, 1)\n",
    "meshc = mesh[c]\n",
    "meshc.faces          # faces of a cell"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((E0, E9, E5),\n",
       " (<ngsolve.comp.ElementId at 0x7fe08e27c7a0>,\n",
       "  <ngsolve.comp.ElementId at 0x7fe08e27c998>))"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f = NodeId(FACE, 2)\n",
    "meshf = mesh[f]\n",
    "meshf.edges, meshf.elements"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "## ElementId and Ngs_Element\n",
    "\n",
    "An `ElementId` is made by an object giving the codimension like `BND` or `VOL`, together with a number.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ngsolve.comp.ElementId"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ei = ElementId(BND,0)\n",
    "type(ei)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As with `NodeId`, we may associate `ElementId` with a mesh to get an object of type `Ngs_Element`, which can be queried for topology information."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "type meshel =  <ngsolve.comp.Ngs_Element object at 0x7fe08e27c110>\n",
      "vertices = (V0, V1, V5)\n"
     ]
    }
   ],
   "source": [
    "meshel = mesh[ei]\n",
    "type(meshel)\n",
    "print (\"type meshel = \", meshel)\n",
    "print (\"vertices =\", meshel.vertices)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that `meshel` has only three vertices because its a *boundary element*. Volume elements have the same type as boundary elements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ngsolve.comp.Ngs_Element"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eiv = ElementId(VOL,0)\n",
    "meshelv = mesh[eiv]\n",
    "type(meshelv)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((V4, V5, V8, V7), (E19, E21, E25, E17, E20, E22), (F28, F27, F23, F24))"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "meshelv.vertices, meshelv.edges, meshelv.facets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Dofs\n",
    "\n",
    "Dofs are numbers enumerating the global *degrees of freedom* of a finite element space. Dofs are associated to mesh entities of the previously described  types.\n",
    "\n",
    "E.g., all dofs of the Lagrange finite element space associated to edges of the mesh can be obtained as follows.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (9, 10, 11)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (12, 13, 14)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (15, 16, 17)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (18, 19, 20)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (21, 22, 23)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (24, 25, 26)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (27, 28, 29)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (30, 31, 32)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (33, 34, 35)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (36, 37, 38)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (39, 40, 41)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (42, 43, 44)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (45, 46, 47)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (48, 49, 50)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (51, 52, 53)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (54, 55, 56)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (57, 58, 59)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (60, 61, 62)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (63, 64, 65)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (66, 67, 68)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (69, 70, 71)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (72, 73, 74)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (75, 76, 77)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (78, 79, 80)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (81, 82, 83)\n",
      "type =  <class 'ngsolve.comp.MeshNode'>\n",
      "dofs =  (84, 85, 86)\n"
     ]
    }
   ],
   "source": [
    "fes = H1(mesh, order=4)\n",
    "for edge in mesh.edges:\n",
    "    print (\"type = \", type(edge)) \n",
    "    print (\"dofs = \", fes.GetDofNrs(edge))   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the output, its evident that these edge dofs are associated to `MeshNode` objects.\n",
    "\n",
    "What about dofs associated to elements?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[4, 5, 8, 7, 66, 67, 68, 72, 73, 74, 84, 85, 86, 60, 61, 62, 69, 70, 71, 75, 76, 77, 171, 172, 173, 168, 169, 170, 156, 157, 158, 159, 160, 161, 177]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[0, 1, 8, 2, 12, 13, 14, 27, 28, 29, 45, 46, 47, 9, 10, 11, 24, 25, 26, 36, 37, 38, 120, 121, 122, 99, 100, 101, 87, 88, 89, 93, 94, 95, 178]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[1, 2, 4, 8, 36, 37, 38, 45, 46, 47, 69, 70, 71, 27, 28, 29, 30, 31, 32, 39, 40, 41, 135, 136, 137, 126, 127, 128, 120, 121, 122, 117, 118, 119, 179]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[0, 3, 8, 5, 18, 19, 20, 48, 49, 50, 75, 76, 77, 15, 16, 17, 24, 25, 26, 57, 58, 59, 144, 145, 146, 111, 112, 113, 102, 103, 104, 108, 109, 110, 180]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[1, 4, 5, 8, 36, 37, 38, 69, 70, 71, 75, 76, 77, 30, 31, 32, 33, 34, 35, 60, 61, 62, 159, 160, 161, 129, 130, 131, 126, 127, 128, 123, 124, 125, 181]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[0, 2, 8, 6, 21, 22, 23, 42, 43, 44, 81, 82, 83, 12, 13, 14, 24, 25, 26, 45, 46, 47, 138, 139, 140, 114, 115, 116, 96, 97, 98, 99, 100, 101, 182]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[0, 3, 6, 8, 24, 25, 26, 57, 58, 59, 81, 82, 83, 15, 16, 17, 21, 22, 23, 51, 52, 53, 150, 151, 152, 114, 115, 116, 108, 109, 110, 105, 106, 107, 183]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[0, 1, 5, 8, 24, 25, 26, 36, 37, 38, 75, 76, 77, 9, 10, 11, 18, 19, 20, 33, 34, 35, 129, 130, 131, 111, 112, 113, 93, 94, 95, 90, 91, 92, 184]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[2, 4, 8, 6, 42, 43, 44, 63, 64, 65, 81, 82, 83, 39, 40, 41, 45, 46, 47, 69, 70, 71, 165, 166, 167, 138, 139, 140, 132, 133, 134, 135, 136, 137, 185]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[4, 6, 7, 8, 69, 70, 71, 81, 82, 83, 84, 85, 86, 63, 64, 65, 66, 67, 68, 78, 79, 80, 174, 175, 176, 168, 169, 170, 165, 166, 167, 162, 163, 164, 186]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[3, 6, 8, 7, 54, 55, 56, 78, 79, 80, 84, 85, 86, 51, 52, 53, 57, 58, 59, 81, 82, 83, 174, 175, 176, 153, 154, 155, 147, 148, 149, 150, 151, 152, 187]\n",
      "<class 'ngsolve.comp.FESpaceElement'>\n",
      "[3, 5, 7, 8, 57, 58, 59, 75, 76, 77, 84, 85, 86, 48, 49, 50, 54, 55, 56, 72, 73, 74, 171, 172, 173, 153, 154, 155, 144, 145, 146, 141, 142, 143, 188]\n"
     ]
    }
   ],
   "source": [
    "for el in fes.Elements(VOL):\n",
    "    print(type(el))\n",
    "    print (el.dofs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The type `ngsolve.comp.FESpaceElement` appearing in the output is derived from `Ngs_Element` as can be seen from the documentation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on class FESpaceElement in module ngsolve.comp:\n",
      "\n",
      "class FESpaceElement(Ngs_Element)\n",
      " |  Method resolution order:\n",
      " |      FESpaceElement\n",
      " |      Ngs_Element\n",
      " |      pybind11_builtins.pybind11_object\n",
      " |      builtins.object\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  GetFE(...)\n",
      " |      GetFE(self: ngsolve.comp.FESpaceElement) -> ngsolve.fem.FiniteElement\n",
      " |      \n",
      " |      the finite element containing shape functions\n",
      " |  \n",
      " |  GetTrafo(...)\n",
      " |      GetTrafo(self: ngsolve.comp.FESpaceElement) -> ngsolve.fem.ElementTransformation\n",
      " |      \n",
      " |      the transformation from reference element to physical element\n",
      " |  \n",
      " |  __init__(self, /, *args, **kwargs)\n",
      " |      Initialize self.  See help(type(self)) for accurate signature.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  dofs\n",
      " |      degrees of freedom of element\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from Ngs_Element:\n",
      " |  \n",
      " |  VB(...)\n",
      " |      VB(self: ngsolve.comp.Ngs_Element) -> ngsolve.comp.VorB\n",
      " |      \n",
      " |      VorB of element\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors inherited from Ngs_Element:\n",
      " |  \n",
      " |  edges\n",
      " |      tuple of global edge numbers\n",
      " |  \n",
      " |  faces\n",
      " |      tuple of global face numbers\n",
      " |  \n",
      " |  facets\n",
      " |      tuple of global face, edge or vertex numbers\n",
      " |  \n",
      " |  index\n",
      " |      material or boundary condition index\n",
      " |  \n",
      " |  mat\n",
      " |      material or boundary condition label\n",
      " |  \n",
      " |  nr\n",
      " |      the element number\n",
      " |  \n",
      " |  type\n",
      " |      geometric shape of element\n",
      " |  \n",
      " |  vertices\n",
      " |      tuple of global vertex numbers\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Methods inherited from pybind11_builtins.pybind11_object:\n",
      " |  \n",
      " |  __new__(*args, **kwargs) from pybind11_builtins.pybind11_type\n",
      " |      Create and return a new object.  See help(type) for accurate signature.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from ngsolve.comp import FESpaceElement\n",
    "help(FESpaceElement)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In later tutorial units, we will have ocasion to use what we learnt here (such as how to iterate over mesh entities) for purposes such as design of smoothing blocks."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
